package com.mybatis.jpa.utils;

import com.mybatis.jpa.exception.JpaException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ObjectFacade {

	private List<FieldFacade> goalFieldFacades = null;
	private List<String> columnNames = null;
	private Class clazz;

	public ObjectFacade(Class clazz) {
		this.clazz = clazz;
	}

	public List<FieldFacade> getFieldFacades() {
		if (goalFieldFacades == null) {
			goalFieldFacades = new ArrayList<>();

			// 使用jacoco生成覆盖率数据收集，在编译时在对象添加属性$jacocoData
			// 如果通过反射获取字段会连$jacocoData属性都获取，导致拼写sql语句把它当成字段
			Field[] fields = clazz.getDeclaredFields();
			Arrays.stream(fields)
					.filter(field -> !StringUtils.contains(field.getName(), "$jacoco"))
					.forEach(field -> goalFieldFacades.add(new FieldFacade(field, clazz)));
		}
		return goalFieldFacades;
	}
	
	public FieldFacade getFiledFacade(String columnName) {
		FieldFacade fieldFacade = null;
		List<FieldFacade> list = this.getFieldFacades();
		for (FieldFacade f : list) {
			if (columnName.equalsIgnoreCase(f.getFieldName())) {
				fieldFacade = f;
				break;
			} 
		}
		JpaException.NullRuntimeException(fieldFacade, "ObjectFacade.getFiledFacade方法：找不到column_name:%s的field; 对象：%s", columnName, this.clazz);
		return fieldFacade;
	}
	
	public List<String> getColumnNames() {
		if (CollectionUtils.isNotEmpty(columnNames)) {
			return columnNames;
		}
		
		columnNames = new ArrayList<>();		
		List<FieldFacade> list = this.getFieldFacades();
		for (FieldFacade fieldFacade : list) {
			Column column = fieldFacade.getField().getAnnotation(Column.class);
			if (column != null && StringUtils.isNotBlank(column.name())) {
				columnNames.add(column.name());
			} else if (column != null) {
				columnNames.add(JpaStringUtils.humpToUnderline(fieldFacade.getFieldName()));
			} else {
				columnNames.add(JpaStringUtils.humpToUnderline(fieldFacade.getFieldName()));
			}
		}
		JpaException.CollectionIsBlankRuntimeException(columnNames, "你确定你不是在逗我吗，对象%s字段全是空的", clazz);
		return columnNames;
	}
	
	/**
	 * 获取主键Field对象
	 * @return Field
	 */
	public FieldFacade getPrimaryKeyField() {
		FieldFacade fieldFacade = null;
		List<FieldFacade> filedFacades = this.getFieldFacades();
		for (FieldFacade ff : filedFacades) {
			Id id = ff.getField().getAnnotation(Id.class);
			if (id != null) {
				fieldFacade = ff;
				break;
			}
		}
		JpaException.NullRuntimeException(fieldFacade, "对象%s没有定义主键", this.clazz);
		return fieldFacade;
	}
	
	public String getPrimaryKeyColumnName() {
		FieldFacade fieldFacade = this.getPrimaryKeyField();
		return fieldFacade.getColumnName();
	}

	public Class getOriginalClass() {
		return clazz;
	}

	public String getTableName() {
		Table table = (Table) clazz.getAnnotation(Table.class);
		if (table == null) {
			// 将类名转换成表名
			return JpaStringUtils.humpToUnderline(clazz.getSimpleName());
		} else {
			return StringUtils.isNotBlank(table.name()) ? table.name() : JpaStringUtils.humpToUnderline(clazz.getSimpleName());
		}
	}
}
